import sqlite3
import requests
import os
from fastapi import FastAPI, Query
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import HTMLResponse, FileResponse, StreamingResponse
from fastapi.staticfiles import StaticFiles
import ast
from PIL import Image
import io
import random
import string
import urllib

app = FastAPI()
db_path = "spider_result/output.db"
# 定义图片缓存目录
image_cache_dir = "image_cache"
if not os.path.exists(image_cache_dir):
    os.makedirs(image_cache_dir)

# 配置 CORS 中间件
origins = [
    "http://localhost",
    "http://localhost:8000",
    "http://127.0.0.1:8000",
    "https://your-frontend-domain.com"  # 替换为你的前端域名
]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"]
)

# 挂载静态文件目录
app.mount("/static", StaticFiles(directory="static"), name="static")


@app.get("/image/{url:path}")
async def get_image(url: str):
    if "http" not in url:
        url = "https:" + url
    # 生成缓存文件路径
    cache_file_name = os.path.join(image_cache_dir, url.replace(":", "_").replace("/", "_"))
    try:
        # 检查缓存文件是否存在
        if os.path.exists(cache_file_name):
            with open(cache_file_name, 'rb') as f:
                image_content = f.read()
        else:
            # 若缓存文件不存在，从网络下载图片
            response = requests.get(url)
            if response.status_code == 200:
                if 'video' in url:
                    return {"error": "视频不支持预览，请直接下载"}
                image_content = response.content
                # 保存图片到缓存
                with open(cache_file_name, 'wb') as f:
                    f.write(image_content)
            else:
                return {"error": "Failed to load image"}

        image = Image.open(io.BytesIO(image_content))
        if image.mode == "P":
            image = image.convert("RGB")
        if image.mode != "RGB":
            image = image.convert("RGBA")
        if image.mode == "RGBA":
            image = image.convert("RGB")
        # 等比例缩小图片
        original_width, original_height = image.size
        ratio = min(300 / original_width, 400 / original_height)
        new_width = int(original_width * ratio)
        new_height = int(original_height * ratio)
        # 调整图片大小
        image = image.resize((new_width, new_height), Image.Resampling.LANCZOS)
        # 将处理后的图片保存到内存中
        output = io.BytesIO()
        image.save(output, format="JPEG")
        output.seek(0)
        return StreamingResponse(
            content=output,
            media_type="image/jpeg"
        )
    except Exception:
        print(url, "处理失败")


# 封装数据卡片的 HTML 部分为函数
def generate_data_card(item):
    html = f"""
    <div class="post">
        <h2>话题: {item[0]}</h2>
        <h5><span class="author">作者: {item[3]}</span> <span class="time">发布时间: {item[4]}</span></h5>
        <p>{item[5]}</p>
    """
    try:
        picture_list = ast.literal_eval(item[6]) if item[6] else []
        if picture_list:
            html += '<div class="image-container">'
            for pic_url in picture_list:
                html += f'''
                <div class="image-container">
                    <img src="/image/{pic_url}" alt="图片">
                    <a href="/download/{pic_url}" class="download-button">下载原图</a>
                </div>
                '''
            html += '</div>'
    except ValueError:
        if item[6]:
            html += f'''
                <div>
                    <img src="/image/{item[6]}" alt="图片">
                    <a href="/download/{item[6]}" class="download-button">下载原图</a>
                </div>
            '''
    html += "</div>"
    return html


# 封装搜索控件
def generate_search_form(name="", content_query="", sort_by="hot"):
    return f"""
    <form action="/data" class="search-form">
        <input type="hidden" name="name" value="{name}">
        <label for="content-input">按内容搜索:</label>
        <input type="text" id="content-input" name="content_query" value="{content_query}">
        <label for="sort-by">排序方式:</label>
        <select id="sort-by" name="sort_by">
            <option value="public_time" {'selected' if sort_by == 'public_time' else ''}>时间</option>
            <option value="hot" {'selected' if sort_by == 'hot' else ''}>热度</option>
        </select>
        <button type="submit" class="action-button">搜索</button>
    </form>
    """


# 封装跳页器控件
def generate_page_jump(name, page, total_pages, sort_by="hot", content_query=""):
    base_url = f"/data?name={name}&page={{page}}&sort_by={sort_by}"
    if content_query:
        base_url += f"&content_query={content_query}"
    prev_page = page - 1 if page > 1 else 1
    next_page = page + 1 if page < total_pages else total_pages
    prev_url = base_url.format(page=prev_page)
    next_url = base_url.format(page=next_page)
    return f"""
    <div class="page-jump">
        <form action="/data">
            <input type="hidden" name="name" value="{name}">
            <input type="hidden" name="sort_by" value="{sort_by}">
            <label for="page-input">跳转至页码:</label>
            <input type="number" id="page-input" name="page" min="1" max="{total_pages}" value="{page}">
            <button type="submit" class="action-button">跳转</button>
            <a href="{prev_url}" class="action-button">上一页</a>
            <a href="{next_url}" class="action-button">下一页</a>
        </form>
    </div>
    """


@app.get("/", response_class=HTMLResponse)
async def module_page(name: str = ""):
    # 连接到 SQLite 数据库
    conn = sqlite3.connect(db_path)
    cursor = conn.cursor()

    # 构建 SQL 查询条件
    conditions = []
    values = []
    if name:
        conditions.append("name LIKE ?")
        values.append(f"%{name}%")

    if conditions:
        where_clause = "WHERE " + " AND ".join(conditions)
        # 查询总记录数
        count_query = f"SELECT COUNT(*) FROM sweibo_data {where_clause}"
        cursor.execute(count_query, values)
        total_count = cursor.fetchone()[0]

        # 获取所有不同的模块名称
        cursor.execute(f'SELECT DISTINCT module FROM sweibo_data {where_clause}', values)
        modules = [row[0] for row in cursor.fetchall()]
    else:
        # 没有搜索条件，查询所有数据
        cursor.execute('SELECT COUNT(*) FROM sweibo_data')
        total_count = cursor.fetchone()[0]

        # 获取所有不同的模块名称
        cursor.execute('SELECT DISTINCT module FROM sweibo_data')
        modules = [row[0] for row in cursor.fetchall()]

    # 按模块分组数据
    module_data = {}
    all_latest_100_data = []
    for module in modules:
        # 构建 SQL 查询条件
        module_conditions = conditions.copy()
        module_conditions.append("module =?")
        module_values = values.copy()
        module_values.append(module)

        if module_conditions:
            module_where_clause = "WHERE " + " AND ".join(module_conditions)
            # 获取每个模块最新的 10 个 name
            cursor.execute(f'SELECT DISTINCT name FROM sweibo_data {module_where_clause} ORDER BY public_time DESC LIMIT 10', module_values)
            names_10 = [row[0] for row in cursor.fetchall()]
            # 获取每个模块的所有 name
            cursor.execute(f'SELECT DISTINCT name FROM sweibo_data {module_where_clause} ORDER BY public_time DESC', module_values)
            all_names = [row[0] for row in cursor.fetchall()]
            # 获取每个模块的最新 100 条数据
            cursor.execute(f'SELECT name, module, hot, author, public_time, content, picture FROM sweibo_data {module_where_clause} ORDER BY public_time DESC LIMIT 100', module_values)
            latest_100_data = cursor.fetchall()
        else:
            # 获取每个模块最新的 10 个 name
            cursor.execute('SELECT DISTINCT name FROM sweibo_data WHERE module =? ORDER BY public_time DESC LIMIT 10', (module,))
            names_10 = [row[0] for row in cursor.fetchall()]
            # 获取每个模块的所有 name
            cursor.execute('SELECT DISTINCT name FROM sweibo_data WHERE module =? ORDER BY public_time DESC', (module,))
            all_names = [row[0] for row in cursor.fetchall()]
            # 获取每个模块的最新 100 条数据
            cursor.execute('SELECT name, module, hot, author, public_time, content, picture FROM sweibo_data WHERE module =? ORDER BY public_time DESC LIMIT 100', (module,))
            latest_100_data = cursor.fetchall()

        module_data[module] = {
            'names_10': names_10,
            'all_names': all_names,
            'latest_100_data': latest_100_data
        }
        all_latest_100_data.extend(latest_100_data)

    conn.close()

    # 按时间排序所有最新数据
    all_latest_100_data.sort(key=lambda x: x[4], reverse=True)
    all_latest_100_data = all_latest_100_data[:10]

    # 构建 HTML 内容
    html_content = f"""
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>微博数据模块展示</title>
        <link rel="stylesheet" href="/static/styles.css">
        <script src="/static/script.js"></script>
    </head>
    <body>
        <h1>微博数据模块展示 - 共 {total_count} 条数据</h1>
        <form action="/" method="get" class="search-form">
            <input type="text" name="name" placeholder="Search by name" value="{name}" class="search-input">
            <input type="submit" value="Search" class="search-button">
            <a href="/"><button type="button" class="reset-button">Reset</button></a>
        </form>
        <div class="module-container">
    """

    for module, data in module_data.items():
        html_content += f"""
        <div class="module">
            <h2>{module}</h2>
            <div id="names-{module}" class="name-list" style="max-height: 450px; overflow-y: auto;">
        """
        for name in data['all_names']:
            encoded_name = urllib.parse.quote(name)
            html_content += f"""
            <div class="name-item">
                <a href="/data?name={encoded_name}" class="name-item">{name}</a>
            </div>
            """
        html_content += f"""
            </div>
        </div>
        """

    # html_content += """
    #     </div>
    #     <div class="latest-data-module">
    #         <h2>最新数据模块</h2>
    # """
    # for item in all_latest_100_data:
    #     html_content += generate_data_card(item)
    
    # html_content += """
    #     </div> 
    # """
    html_content += """
    </body>
    </html>
    """
    return html_content


@app.get("/data", response_class=HTMLResponse)
async def data_page(
    name: str,
    page: int = Query(1, ge=1),
    content_query: str = Query("", description="内容搜索关键词"),
    sort_by: str = Query("hot", description="排序方式，可选值：hot（热度），public_time（时间）")
):
    name = urllib.parse.unquote(name)
    items_per_page = 20
    offset = (page - 1) * items_per_page

    # 连接到 SQLite 数据库
    conn = sqlite3.connect(db_path)
    cursor = conn.cursor()

    # 构建 SQL 查询条件
    conditions = []
    values = []
    conditions.append("name =?")
    values.append(name)
    if content_query:
        conditions.append("content LIKE ?")
        values.append(f"%{content_query}%")

    # 根据排序方式调整 SQL 排序语句
    if sort_by == "hot":
        order_by = "CAST(hot AS SIGNED) desc, public_time desc"
    elif sort_by == "public_time":
        order_by = "public_time desc, CAST(hot AS SIGNED) desc"
    else:
        order_by = "CAST(hot AS SIGNED) desc, public_time desc"

    if conditions:
        where_clause = "WHERE " + " AND ".join(conditions)
        # 查询总记录数
        count_query = f"SELECT COUNT(*) FROM sweibo_data {where_clause}"
        cursor.execute(count_query, values)
        total_count = cursor.fetchone()[0]

        # 查询当前页的数据
        data_query = f"SELECT name, module, hot, author, public_time, content, picture FROM sweibo_data {where_clause} ORDER BY {order_by} LIMIT ? OFFSET ?"
        values.extend([items_per_page, offset])
        cursor.execute(data_query, values)
    else:
        # 没有搜索条件，查询所有数据
        cursor.execute('SELECT COUNT(*) FROM sweibo_data WHERE name =?', (name,))
        total_count = cursor.fetchone()[0]

        cursor.execute(f'SELECT name, module, hot, author, public_time, content, picture FROM sweibo_data WHERE name =? ORDER BY {order_by} LIMIT ? OFFSET ?',
                       (name, items_per_page, offset))

    data = cursor.fetchall()
    conn.close()

    # 计算总页数
    total_pages = (total_count + items_per_page - 1) // items_per_page

    # 构建 HTML 内容
    html_content = f"""
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>微博话题  {name}  共 {total_count} 条数据，第 {page} 页 / 共 {total_pages} 页</title>
        <link rel="stylesheet" href="/static/styles.css">
    </head>
    <body>
        <h1>微博话题  {name}  共 {total_count} 条数据，第 {page} 页 / 共 {total_pages} 页</h1>
        <a href="/" class="action-button">返回模块列表</a>
        {generate_page_jump(name, page, total_pages, sort_by, content_query)}
        {generate_search_form(name, content_query, sort_by)}
    """

    for item in data:
        html_content += generate_data_card(item)

    html_content += generate_page_jump(name, page, total_pages, sort_by, content_query)
    html_content += """
    </body>
    </html>
    """
    return html_content


@app.get("/download/{url:path}")
async def download_image(url: str):
    if "http" not in url:
        url = "https:" + url
    try:
        response = requests.get(url)
        if response.status_code == 200:
            if 'video' in url:
                extension = 'mp4'
            else:
                extension = 'jpg'
            # 这里假设当前目录下有一个 downloads 文件夹用于保存下载的文件
            if not os.path.exists('downloads'):
                os.makedirs('downloads')
            url_path = url.split("/")[-1]
            image_path = os.path.join('downloads', url_path)
            with open(image_path, 'wb') as f:
                f.write(response.content)
            return FileResponse(image_path, headers={"Content-Disposition": f"attachment; filename={url_path}"})
        return {"error": "Failed to download image"}
    except Exception as e:
        print(url, "下载失败:", e)
        return {"error": f"Failed to download image: {str(e)}"}